package com.ssy.lingxi.purchase.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberInnerControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignRoleVO;
import com.ssy.lingxi.purchase.api.common.OrderConstant;
import com.ssy.lingxi.purchase.api.common.PurchaseInquiryConstant;
import com.ssy.lingxi.purchase.api.dto.request.BaseDetailsRequest;
import com.ssy.lingxi.purchase.api.dto.request.bidding.BiddingListRequest;
import com.ssy.lingxi.purchase.api.dto.request.bidding.BiddingProductRequest;
import com.ssy.lingxi.purchase.api.dto.response.LogStateResponse;
import com.ssy.lingxi.purchase.api.dto.response.bidding.*;
import com.ssy.lingxi.purchase.api.dto.response.online.OfferLogsResponse;
import com.ssy.lingxi.purchase.api.enums.bidding.*;
import com.ssy.lingxi.purchase.api.enums.onlinebidding.OnlineBiddingExternalWorkStateEnum;
import com.ssy.lingxi.purchase.api.enums.purchase.StatusEnum;
import com.ssy.lingxi.purchase.entity.bidding.*;
import com.ssy.lingxi.purchase.entity.onlinebidding.OnLineBidding;
import com.ssy.lingxi.purchase.entity.onlinebidding.OnLineBiddingProduct;
import com.ssy.lingxi.purchase.entity.onlinebidding.OnlineMateriel;
import com.ssy.lingxi.purchase.repository.bidding.*;
import com.ssy.lingxi.purchase.repository.online.OnLineBiddingRepository;
import com.ssy.lingxi.purchase.repository.online.OnlineMaterielRepository;
import com.ssy.lingxi.workflow.api.feign.ProcessFeign;
import com.ssy.lingxi.workflow.api.model.contant.ProcessEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.*;
import com.ssy.lingxi.workflow.api.model.vo.response.ComplexTaskCompleteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleProcessDefVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public abstract class BaseBiddingService {

    private static final ObjectMapper mapper = new ObjectMapper();
    @Resource
    BiddingRepository biddingRepository;
    @Resource
    BiddingProductRepository biddingProductRepository;
    @Resource
    ExternalBiddingLogRepository externalBiddingLogRepository;
    @Resource
    InteriorBiddingLogRepository interiorBiddingLogRepository;
    @Resource
    BiddingDemandMemberRepository biddingDemandMemberRepository;
    @Resource
    ProcessFeign taskExecuteControllerFeign;
    @Resource
    OnLineBiddingRepository onLineBiddingRepository;
    @Resource
    IRedisStringUtils redisStringUtils;
    @Resource
    MemberInnerControllerFeign memberInnerControllerFeign;
    @Resource
    OnlineMaterielRepository onlineMaterielRepository;

    /**
     * 根据不同类型查询采购竞价单列表 queryType：
     */
    public Wrapper<PageData<BiddingListResponse>> getQuery(UserLoginCacheDTO sysUser, BiddingListRequest request, Integer queryType) {
        Specification<Bidding> biddingQuery = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            //创建会员
            predicates.add(criteriaBuilder.equal(root.get("createMemberId").as(Long.class), sysUser.getMemberId()));
            predicates.add(criteriaBuilder.equal(root.get("createMemberRoleId").as(Long.class), sysUser.getMemberRoleId()));
            //会员名称
            if (StringUtils.hasLength(request.getMemberName()))
                predicates.add(criteriaBuilder.like(root.get("createMemberName"), "%" + request.getMemberName() + "%"));
            //竞价单创建时间
            if (null != request.getStartTime()) {
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), request.getStartTime()));
            }
            if (null != request.getEndTime()) {
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime"), request.getEndTime()));
            }
            //摘要
            if (StringUtils.hasLength(request.getDetails())) {
                predicates.add(criteriaBuilder.like(root.get("details"), "%" + request.getDetails() + "%"));
            }
            //竞价单号
            if (StringUtils.hasLength(request.getBiddingNo())) {
                predicates.add(criteriaBuilder.like(root.get("biddingNo"), "%" + request.getBiddingNo() + "%"));
            }
            //查询竞价单类型
            if (request.getShopType() != null) {
                predicates.add(criteriaBuilder.equal(root.get("shopType"), request.getShopType()));
            }
            //采购竞价单
            if (BiddingListEnum.PURCHASE_BIDDING_LIST.getType().equals(queryType)) {
                if (null != request.getExternalState()) {
                    predicates.add(criteriaBuilder.equal(root.get("externalState"), request.getExternalState()));
                }
                if (null != request.getInteriorState()) {
                    predicates.add(criteriaBuilder.equal(root.get("interiorState"), request.getInteriorState()));
                }
            //待新增采购竞价单
            } else if (BiddingListEnum.ADD_PURCHASE_BIDDING_LIST.getType().equals(queryType) || BiddingListEnum.ADD_SHOP_PURCHASE_BIDDING_LIST.getType().equals(queryType)) {
                //外部状态为 待提交采购竞价单
                predicates.add(criteriaBuilder.equal(root.get("externalState"), BiddingExternalWorkStateEnum.STAY_SUBMIT_BIDDING.getState()));
                //内部状态为 待提交审核采购竞价单、采购竞价单审核不通过(一级)、二级
                List<Integer> inTatus = Arrays.asList(BiddingInteriorWorkStateEnum.STAY_SUBMIT_BIDDING.getState(), BiddingInteriorWorkStateEnum.AUDIT_NOT_BIDDING1.getState(), BiddingInteriorWorkStateEnum.AUDIT_NOT_BIDDING2.getState());
                predicates.add(criteriaBuilder.in(root.get("interiorState")).value(inTatus));
            //待审核采购竞价单(一级)
            } else if (BiddingListEnum.EXAMINE_PURCHASE_BIDDING_LIST1.getType().equals(queryType)) {
                //外部状态为 待提交采购竞价单
                predicates.add(criteriaBuilder.equal(root.get("externalState"), BiddingExternalWorkStateEnum.STAY_SUBMIT_BIDDING.getState()));
                //内部状态为 待审核采购竞价单(一级)
                predicates.add(criteriaBuilder.equal(root.get("interiorState"), BiddingInteriorWorkStateEnum.STAY_AUDIT_BIDDING1.getState()));
            //待审核采购竞价单(二级)
            } else if (BiddingListEnum.EXAMINE_PURCHASE_BIDDING_LIST2.getType().equals(queryType)) {
                //外部状态为 待提交采购竞价单
                predicates.add(criteriaBuilder.equal(root.get("externalState"), BiddingExternalWorkStateEnum.STAY_SUBMIT_BIDDING.getState()));
                //内部状态为 待审核采购竞价单(二级)
                predicates.add(criteriaBuilder.equal(root.get("interiorState"), BiddingInteriorWorkStateEnum.STAY_SUBMIT_BIDDING2.getState()));
            //待提交采购竞价单
            } else if (BiddingListEnum.SUBMIT_PURCHASE_BIDDING_LIST.getType().equals(queryType)) {
                //外部状态为 待提交采购竞价单
                predicates.add(criteriaBuilder.equal(root.get("externalState"), BiddingExternalWorkStateEnum.STAY_SUBMIT_BIDDING.getState()));
                //内部状态为 待提交采购竞价单
                predicates.add(criteriaBuilder.equal(root.get("interiorState"), BiddingInteriorWorkStateEnum.STAY_CONFIRMATION_BIDDING.getState()));
            //待竞价
            } else if (BiddingListEnum.STAY_BIDDING.getType().equals(queryType)) {
                //外部状态为 待竞价
                predicates.add(criteriaBuilder.equal(root.get("externalState"), BiddingExternalWorkStateEnum.STAY_BIDDING.getState()));
                //内部状态为 待管理竞价
                predicates.add(criteriaBuilder.equal(root.get("interiorState"), BiddingInteriorWorkStateEnum.SIGNUP_EXAMIN_NOT2.getState()));
            }
            Predicate[] predicate = new Predicate[predicates.size()];
            return criteriaBuilder.and(predicates.toArray(predicate));
        };
        Page<Bidding> biddingS = biddingRepository.findAll(biddingQuery, PageRequest.of(request.getCurrent(), request.getPageSize(), Sort.by("createTime").descending()));
        if (0 < biddingS.getTotalElements()) {
            return Wrapper.success(new PageData<>(biddingS.getTotalElements(), biddingS.getContent().stream().map(temp -> {
                BiddingListResponse response = BeanUtil.copyProperties(temp, BiddingListResponse.class);
                response.setInteriorStateName(BiddingInteriorWorkStateEnum.getName(temp.getInteriorState()));
                response.setExternalStateName(BiddingExternalWorkStateEnum.getName(temp.getExternalState()));
                return response;
            }).collect(Collectors.toList())));
        }else {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }
    }


    /**
     * 查询采购竞价单- 内部审核流转状态
     */
    public List<LogStateResponse> getLogStateInterior(Integer processEnum, Integer nextStep) {
        InternalProcessQueryVO taskParamQueryVO = new InternalProcessQueryVO();
        taskParamQueryVO.setProcessKey(ProcessEnum.getProcessKeyByCode(processEnum));
        Wrapper<SimpleProcessDefVO> listWrapper = taskExecuteControllerFeign.findSimpleInternalTaskDefinitions(taskParamQueryVO);
        if (ResponseCode.SUCCESS.getCode() != listWrapper.getCode()) {
            throw new RuntimeException(listWrapper.getMessage());
        }
        List<SimpleTaskVO> data = listWrapper.getData().getTasks();
        return data.stream().map(taskStepQueryVO -> {
            LogStateResponse quotationState = new LogStateResponse();
            quotationState.setOperationalProcess(taskStepQueryVO.getTaskName());
            quotationState.setRoleName(taskStepQueryVO.getRoleName());
            quotationState.setIsExecute((null != nextStep && nextStep >= taskStepQueryVO.getTaskStep()) ? OrderConstant.State.START : OrderConstant.State.STOP);
            quotationState.setState(taskStepQueryVO.getTaskStep());
            quotationState.setStateName(BiddingInteriorWorkStepEnum.getName(taskStepQueryVO.getTaskStep()));
            return quotationState;
        }).collect(Collectors.toList());
    }

    /**
     * 查询采购竞价单流转状态 外部
     */
    public List<LogStateResponse> getLogStateExternal(Integer processEnum, Integer nextStep,Long roleId,Long upperRoleId) {
        ExternalProcessQueryVO taskParamQueryVO = new ExternalProcessQueryVO();
        taskParamQueryVO.setProcessKey(ProcessEnum.getProcessKeyByCode(processEnum));
        taskParamQueryVO.setRoleId(roleId);
        taskParamQueryVO.setSubRoleId(upperRoleId);
        Wrapper<SimpleProcessDefVO> listWrapper = taskExecuteControllerFeign.findSimpleExternalTaskDefinitions(taskParamQueryVO);
        if (ResponseCode.SUCCESS.getCode() != listWrapper.getCode()) {
            throw new RuntimeException(listWrapper.getMessage());
        }
        List<SimpleTaskVO> data = listWrapper.getData().getTasks();
        return data.stream().map(taskStepQueryVO -> {
            LogStateResponse quotationState = new LogStateResponse();
            quotationState.setOperationalProcess(taskStepQueryVO.getTaskName());
            quotationState.setRoleName(taskStepQueryVO.getRoleName());
            quotationState.setIsExecute((null != nextStep && nextStep >= taskStepQueryVO.getTaskStep()) ? OrderConstant.State.START : OrderConstant.State.STOP);
            quotationState.setState(taskStepQueryVO.getTaskStep());
            quotationState.setStateName(BiddingExternalWorkStateEnum.getName(taskStepQueryVO.getTaskStep()));
            return quotationState;
        }).collect(Collectors.toList());
    }


    /**
     * 记录采购竞价单外部操作记录
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveExternalLog(UserLoginCacheDTO sysUser, Integer operation, Integer state, Long biddingId, Integer externalLogType, String auditOpinion, Long memberId, Long memberRoleId) {
        //记录操作记录
        ExternalBiddingLog externalLog = new ExternalBiddingLog();
        externalLog.setRoleName(sysUser.getMemberRoleName());
        externalLog.setBiddingId(biddingId);
        externalLog.setExternalLogType(externalLogType);
        externalLog.setState(state);
        externalLog.setOperation(operation);
        externalLog.setAuditOpinion(auditOpinion);
        externalLog.setCreateTime(System.currentTimeMillis());
        externalLog.setCreateMemberId(sysUser.getMemberId());
        externalLog.setCreateMemberRoleId(sysUser.getMemberRoleId());
        externalLog.setOperatedMemberId(memberId);
        externalLog.setOperatedMemberRoleId(memberRoleId);
        externalBiddingLogRepository.saveAndFlush(externalLog);
    }


    /**
     * 采购商查询采购竞价单外部操作记录
     */
    public List<ExternalBiddingLogResponse> getExternalLog(Long biddingId) {
        List<ExternalBiddingLog> externalLogs = externalBiddingLogRepository.findAllByBiddingId(biddingId, Sort.by("createTime").ascending());
        if (CollectionUtils.isEmpty(externalLogs)) {
            return new ArrayList<>();
        }
        List<ExternalBiddingLogResponse> list = new ArrayList<>();
        List<ExternalBiddingLogResponse> supperList = new ArrayList<>();
        externalLogs.forEach(temp -> {
            ExternalBiddingLogResponse logResponse = new ExternalBiddingLogResponse();
            BeanUtils.copyProperties(temp, logResponse);
            logResponse.setOperation(BiddingOperationStateEnum.getName(temp.getOperation()));
            logResponse.setAuditOpinion(StatusEnum.AGREE.getCHName().equals(temp.getAuditOpinion()) ? StatusEnum.AGREE.getName() : temp.getAuditOpinion());
            if (logResponse.getExternalLogType() != null){
                logResponse.setStateName(OnlineBiddingExternalWorkStateEnum.getName(temp.getState()));
                supperList.add(logResponse);
            }else {
                logResponse.setStateName(BiddingExternalWorkStateEnum.getName(temp.getState()));
                list.add(logResponse);
            }
        });
        //筛选供应商记录, 只保留一条
        Map<Integer, List<ExternalBiddingLogResponse>> listMap = supperList.stream().collect(Collectors.groupingBy(ExternalBiddingLogResponse::getExternalLogType));
        for (Integer integer : listMap.keySet()) {
            list.add(listMap.get(integer).get(0));
        }
        return list;
    }

    /**
     * 供应商查询采购竞价单外部操作记录
     */
    public List<ExternalBiddingLogResponse> getSupplyExternalLog(Long biddingId, Long memberId, Long memberRoleId) {

        List<ExternalBiddingLog> externalLogs = externalBiddingLogRepository.findAllByBiddingId(biddingId, Sort.by("createTime").ascending());
        if (CollectionUtils.isEmpty(externalLogs)) {
            return new ArrayList<>();
        }
        List<ExternalBiddingLogResponse> list = new ArrayList<>();
        externalLogs.forEach(temp -> {
            ExternalBiddingLogResponse logResponse = new ExternalBiddingLogResponse();
            BeanUtils.copyProperties(temp, logResponse);
            logResponse.setOperation(BiddingOperationStateEnum.getName(temp.getOperation()));
            logResponse.setAuditOpinion(StatusEnum.AGREE.getCHName().equals(temp.getAuditOpinion()) ? StatusEnum.AGREE.getName() : temp.getAuditOpinion());
            if (logResponse.getExternalLogType() != null){
                //筛选当前供应商关联的内部记录
                if (memberId.equals(temp.getOperatedMemberId()) && memberRoleId.equals(temp.getOperatedMemberRoleId())){
                    logResponse.setStateName(OnlineBiddingExternalWorkStateEnum.getName(temp.getState()));
                    list.add(logResponse);
                }
            }else {
                logResponse.setStateName(BiddingExternalWorkStateEnum.getName(temp.getState()));
                list.add(logResponse);
            }
        });
        return list;
    }

    /**
     * 启动工作流
     */
    public Wrapper<SimpleTaskCompleteVO> startWork(UserLoginCacheDTO sysUser, Long id, Integer processEnum) {
        TaskStartVO processStartVO = new TaskStartVO();
        processStartVO.setMemberId(sysUser.getMemberId());
        processStartVO.setRoleId(sysUser.getMemberRoleId());
        processStartVO.setProcessKey(ProcessEnum.getProcessKeyByCode(processEnum));
        processStartVO.setDataId(id);
        return taskExecuteControllerFeign.startSimpleProcess(processStartVO);
    }

    /**
     * 记录采购竞价单内部操作记录
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveInteriorLog(UserLoginCacheDTO sysUser, Integer operation, Integer state, Integer step, Long id, String auditOpinion) {
        //记录操作记录
        InteriorBiddingLog interiorLog = new InteriorBiddingLog();
        interiorLog.setRoleName(sysUser.getUserName());
        interiorLog.setDepartment(sysUser.getUserOrgName());
        interiorLog.setPosition(sysUser.getUserJobTitle());
        interiorLog.setBiddingId(id);
        interiorLog.setState(state);
        interiorLog.setStep(step);
        interiorLog.setOperation(operation);
        interiorLog.setAuditOpinion(auditOpinion);
        interiorLog.setCreateTime(System.currentTimeMillis());
        interiorLog.setCreateRoleId(sysUser.getMemberRoleId());
        interiorLog.setCreateMemberId(sysUser.getMemberId());
        interiorBiddingLogRepository.saveAndFlush(interiorLog);
    }

    /**
     * 判断采购竞价单是否有提交过审核
     */
    public Boolean judgeInteriorLog(Long biddingId) {
        List<InteriorBiddingLog> interiorBiddingLogs = interiorBiddingLogRepository.findAllByBiddingId(biddingId);
        if (CollectionUtils.isEmpty(interiorBiddingLogs)){
            return true;
        }
        return interiorBiddingLogs.stream().noneMatch(interiorBiddingLog -> BiddingOperationStateEnum.SUBMIT_AUDIT_BIDDING.getState().equals(interiorBiddingLog.getOperation()));
    }

    /**
     * 执行工作流- 单次执行
     */
    public Wrapper<SimpleTaskCompleteVO> executeWork(Long memberId, Long memberRoleId, Long id, Integer processEnum, Integer step, String taskId, Integer agree) {
        TaskExecuteVO processStartVO = new TaskExecuteVO();
        processStartVO.setMemberId(memberId);
        processStartVO.setRoleId(memberRoleId);
        processStartVO.setProcessKey(ProcessEnum.getProcessKeyByCode(processEnum));
        processStartVO.setAgree(agree);
        processStartVO.setTaskId(taskId);
        processStartVO.setDataId(id);
        return taskExecuteControllerFeign.completeSimpleTask(processStartVO);
    }

    /**
     * 执行工作流- 多次执行
     */
    public Wrapper<ComplexTaskCompleteVO> executeWorks(Long memberId, Long memberRoleId, Long id, Integer processEnum, Integer step, String taskId, List<Integer> agrees, Integer execTimes) {
        SerialTaskExecuteVO executeVO = new SerialTaskExecuteVO();
        executeVO.setProcessKey(ProcessEnum.getProcessKeyByCode(processEnum));
        executeVO.setMemberId(memberId);
        executeVO.setRoleId(memberRoleId);
        executeVO.setDataId(id);
        executeVO.setTaskId(taskId);
        executeVO.setExecTimes(execTimes);
        executeVO.setAgrees(agrees);
        return taskExecuteControllerFeign.completeSerialTasks(executeVO);
    }

    /**
     * 当前供应商竞价过程
     */
    public List<AwardProcessResponse> getAwardProces(Long biddingId, UserLoginCacheDTO sysUser) throws JsonProcessingException {
        OnLineBidding onLineBidding = onLineBiddingRepository.findFirstByBiddingId(biddingId);
        //有效竞标次数要大于等于1
        if (Objects.isNull(onLineBidding) || onLineBidding.getCount() <= 0) {
            return new ArrayList<>();
        }
        OnlineMateriel onlineMateriel = onLineBidding.getMateriels().stream().filter(temp -> sysUser.getMemberId().equals(temp.getCreateMemberId()) && sysUser.getMemberRoleId().equals(temp.getCreateMemberRoleId())).findFirst().orElse(null);
        if (Objects.isNull(onlineMateriel) || StatusEnum.NO.getState().equals(onlineMateriel.getIsOffer())){
            return new ArrayList<>();
        }
        List<OnLineBiddingProduct> products = onlineMateriel.getProducts();
        if (CollectionUtils.isEmpty(products)){
            return new ArrayList<>();
        }
        //按照报价次数分组
        Map<Long, List<OnLineBiddingProduct>> listMap = products.stream().collect(Collectors.groupingBy(OnLineBiddingProduct::getReportNumber));

        //查询当前供应商报价信息
        String key = sysUser.getMemberId() + "_" + sysUser.getMemberRoleId();
        String object = redisStringUtils.hGet(PurchaseInquiryConstant.BIDDING_RANKING_LIST_DETAILS + onLineBidding.getId(), key, Constants.PURCHASE_INDEX);
        QueryPriceDynamicResponse dynamicResponse = null;
        if (StringUtils.hasLength(object)){
            Map<String, String> map = mapper.readValue(object, new TypeReference<Map<String, String>>() {});
            List<QueryPriceDynamicResponse> queryPrices = new ArrayList<>();
            for (String next : map.keySet()) {
                String str = map.get(next);
                dynamicResponse = mapper.readValue(str, new TypeReference<QueryPriceDynamicResponse>() {});
                queryPrices.add(dynamicResponse);
            }
            queryPrices = queryPrices.stream().sorted(Comparator.comparing(QueryPriceDynamicResponse::getCount).reversed()).collect(Collectors.toList());
            //获取最后一次报价历史
            dynamicResponse = queryPrices.get(queryPrices.size() - 1);
        }

        List<AwardProcessResponse> collect = listMap.values().stream().map(value -> {
            AwardProcessResponse response = new AwardProcessResponse();
            response.setId(onLineBidding.getId());
            response.setSumPice(value.stream().mapToDouble(OnLineBiddingProduct::getPrice).sum());
            OnLineBiddingProduct product = value.get(0);
            response.setMemberId(onlineMateriel.getCreateMemberId());
            response.setMemberRoleId(onlineMateriel.getCreateMemberRoleId());
            response.setMemberName(onlineMateriel.getCreateMemberName());
            response.setPeportTime(product.getReportTime());
            response.setPeportPriceSum(product.getReportNumber());
            response.setDetailss(value.stream().map(details -> BeanUtil.copyProperties(details, AwardProcessDetailsResponse.class)).collect(Collectors.toList()));
            response.setRanking(product.getRanking());
            response.setMinPrice(product.getMinPrice());
            return response;
        }).sorted(Comparator.comparing(AwardProcessResponse::getPeportPriceSum)).collect(Collectors.toList());
        //获取最后一次排名
        if (Objects.nonNull(dynamicResponse)) {
            collect.get(collect.size() - 1).setRanking(dynamicResponse.getCount());
        }
        return collect;
    }

    /**
     * 采购商查看所有供应商竞价过程
     */
    public List<AwardProcessResponse> getAwardProcess(Long biddingId) {
        OnLineBidding onLineBidding = onLineBiddingRepository.findFirstByBiddingId(biddingId);
        //有效竞标次数要大于等于1
        if (Objects.isNull(onLineBidding) || onLineBidding.getCount() <= 0) {
            return new ArrayList<>();
        }
        List<OnlineMateriel> materiels = onLineBidding.getMateriels().stream().filter(materiel -> StatusEnum.YES.getState().equals(materiel.getIsOffer())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(materiels) || materiels.stream().allMatch(materiel -> CollectionUtils.isEmpty(materiel.getProducts()))){
            return new ArrayList<>();
        }
        //按照供应会员分组(过滤未报价会员)
        Map<String, List<OnLineBiddingProduct>> collect = materiels.stream().filter(materiel ->StatusEnum.YES.getState().equals(materiel.getIsOffer())).collect(Collectors.toMap(OnlineMateriel::getCreateMemberName, OnlineMateriel::getProducts));
        List<AwardProcessResponse> responses = new ArrayList<>();
        collect.keySet().forEach(str ->{
            List<OnLineBiddingProduct> products = collect.get(str);
            //按照报价次数分组
            Map<Long, List<OnLineBiddingProduct>> map = products.stream().collect(Collectors.groupingBy(OnLineBiddingProduct::getReportNumber));
            //获取最后一次报价信息
            for (Long reportNumber : map.keySet()) {
                List<OnLineBiddingProduct> productList = map.get(reportNumber);
                AwardProcessResponse response = new AwardProcessResponse();
                response.setId(onLineBidding.getId());
                OnLineBiddingProduct product = productList.get(0);
                OnlineMateriel materiel = product.getOnlineMateriel();
                response.setSumPice(productList.stream().mapToDouble(OnLineBiddingProduct::getPrice).sum());
                response.setMemberId(materiel.getCreateMemberId());
                response.setMemberRoleId(materiel.getCreateMemberRoleId());
                response.setMemberName(materiel.getCreateMemberName());
                response.setPeportTime(product.getReportTime());
                response.setCountPriceSum((long) products.size());
                response.setPeportPriceSum(product.getReportNumber());
                response.setDetailss(productList.stream().map(details -> BeanUtil.copyProperties(details, AwardProcessDetailsResponse.class)).collect(Collectors.toList()));
                responses.add(response);
            }
        });
        Map<Long, List<AwardProcessResponse>> listMap = responses.stream().collect(Collectors.groupingBy(AwardProcessResponse::getMemberId));
        for (Long memberId : listMap.keySet()) {
            List<AwardProcessResponse> responseList = listMap.get(memberId);
            //给供应商报价记录排序
            List<AwardProcessResponse> list = responseList.stream().sorted(Comparator.comparing(AwardProcessResponse::getPeportPriceSum)).collect(Collectors.toList());
            for (int i = 0; i < list.size(); i++) {
                list.get(i).setCountPriceSum((long)i + 1);
            }
        }
        return responses;
    }

    /**
     * 供应商实时竞价 - 报价台信息
     * @param webSocketBidding  实时竞价信息封装类
     * @param onLineBidding     在线竞价实体
     * @param onlineMateriel    供应商竞价信息
     */
    public void assembleWebSocketQueryPrice(WebSocketBiddingSupplierResponse webSocketBidding, OnLineBidding onLineBidding, OnlineMateriel onlineMateriel) throws JsonProcessingException {
        //获取供应商报价缓存信息
        String key = onlineMateriel.getCreateMemberId() + "_" + onlineMateriel.getCreateMemberRoleId();
        String object = redisStringUtils.hGet(PurchaseInquiryConstant.BIDDING_RANKING_LIST_DETAILS + onLineBidding.getId(), key, Constants.PURCHASE_INDEX);
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String> map = mapper.readValue(object, new TypeReference<Map<String, String>>() {});
        List<QueryPriceDynamicResponse> queryPrices = new ArrayList<>();
        for (String next : map.keySet()) {
            String str = map.get(next);
            QueryPriceDynamicResponse dynamicResponse = mapper.readValue(str, new TypeReference<QueryPriceDynamicResponse>() {});
            queryPrices.add(dynamicResponse);
        }
        //报价台信息
        List<WebSocketAwardProcessResponse> awardProcess = new ArrayList<>();
        //报价历史信息
        List<OfferLogsResponse> offerLogs = new ArrayList<>();
        queryPrices.forEach(queryPrice ->{
            WebSocketAwardProcessResponse awardProces = new WebSocketAwardProcessResponse();
            awardProces.setMinPrice(queryPrice.getMinPrice());
            awardProces.setSumPice(queryPrice.getSumPrice());
            awardProces.setPeportTime(queryPrice.getQueryPriceTime());
            awardProcess.add(awardProces);
            OfferLogsResponse offerLog = new OfferLogsResponse();
            offerLog.setOfferCount(queryPrice.getCount());
            offerLog.setOfferPrice(queryPrice.getSumPrice());
            offerLog.setOfferRatio(queryPrice.getOfferRatio());
            offerLog.setRanking(queryPrice.getRanking());
            offerLog.setMinPrice(queryPrice.getMinPrice());
            offerLog.setOfferTime(queryPrice.getQueryPriceTime());
        });
        webSocketBidding.setAwardProcesss(awardProcess);
        webSocketBidding.setOfferLogs(offerLogs);
        //最低价报价
        OfferLogsResponse logsResponse = offerLogs.stream().min(Comparator.comparing(OfferLogsResponse::getOfferPrice)).orElse(null);
        webSocketBidding.setId(onLineBidding.getId());
        BeanUtil.copyProperties(logsResponse, webSocketBidding);
    }

    /**
     * 竞价排名-竞价管理
     */
    public List<QuotationRankingResponse> rankingBidding(BaseDetailsRequest request) {
        Bidding bidding = biddingRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(bidding)){
            return new ArrayList<>();
        }
        OnLineBidding onLineBidding = onLineBiddingRepository.findFirstByBiddingId(bidding.getId());
        if (Objects.isNull(onLineBidding)){
            return new ArrayList<>();
        }
//        //先从缓存查询排名信息
//        Set<String> zSet = redisStringUtils.getZSet(PurchaseInquiryConstant.BIDDING_RANKING_LIST_KEY + onLineBidding.getId(), request.getCurrent(), request.getPageSize());
//        List<String> ranges = new ArrayList<>(zSet);
//        Map<String, String> map = redisStringUtils.hGetAll(PurchaseInquiryConstant.BIDDING_RANKING_LIST_DETAILS + onLineBidding.getId(), Constants.PURCHASE_INDEX);
//        if (!CollectionUtils.isEmpty(ranges) && !CollectionUtils.isEmpty(map)) {
//            List<QueryPriceDynamicResponse> queryPrices = new ArrayList<>();
//            for (String range : ranges) {
//                try {
//                    Map<String, String> result = mapper.readValue(map.get(range), new TypeReference<Map<String, String>>() {});
//                    for (String next : result.keySet()) {
//                        String str = result.get(next);
//                        QueryPriceDynamicResponse dynamicResponse = mapper.readValue(str, new TypeReference<QueryPriceDynamicResponse>() {});
//                        queryPrices.add(dynamicResponse);
//                    }
//                } catch (JsonProcessingException e) {
//                    log.error("竞价排名JSON解析异常", e);
//                    throw new BusinessException(ResponseCode.PARSING_EXCEPTION);
//                }
//            }
//            //最低报价信息
//            return queryPrices.stream().map(dynamicResponse -> BeanUtil.copyProperties(dynamicResponse, QuotationRankingResponse.class)).collect(Collectors.toList());
//        }

        //查询数据库
        //所有竞价会员信息(已竞价)
        List<QuotationRankingResponse> list = new ArrayList<>();
        List<OnlineMateriel> materiels = onlineMaterielRepository.findAllByOnlineBiddingIdAndIsOffer(onLineBidding.getId(), StatusEnum.YES.getState());
        if (CollectionUtils.isEmpty(materiels)){
            return list;
        }
        list = materiels.stream().map(materiel -> {
            QuotationRankingResponse quotationRankingResponse = new QuotationRankingResponse();
            quotationRankingResponse.setContacts(materiel.getContacts());
            quotationRankingResponse.setMemberName(materiel.getCreateMemberName());
            quotationRankingResponse.setMemberId(materiel.getCreateMemberId());
            quotationRankingResponse.setMemberRoleId(materiel.getCreateMemberRoleId());
            quotationRankingResponse.setQueryPriceTime(materiel.getReportTime());
            quotationRankingResponse.setSumPrice(materiel.getSumPrice());
            quotationRankingResponse.setCount(materiel.getPeportPriceSum());
            return quotationRankingResponse;
        }).sorted(Comparator.comparing(QuotationRankingResponse::getSumPrice)).collect(Collectors.toList());
        //添加排名
        for (int i = 0; i < list.size(); i++) {
            QuotationRankingResponse response = list.get(i);
            response.setRanking((long)i + 1);
        }
        return list;
    }

    /**
     * 授标结果
     */
    public AwardsFruitsResponse getAwardsFruits(Long biddingId) {
        OnLineBidding onLineBidding = onLineBiddingRepository.findFirstByBiddingId(biddingId);
        //有效竞标次数要大于等于1
        if (Objects.isNull(onLineBidding) || onLineBidding.getCount() <= 0) {
            return new AwardsFruitsResponse();
        }
        AwardsFruitsResponse response = new AwardsFruitsResponse();
        response.setId(onLineBidding.getId());
        //按照名次顺序排列
        List<OnlineMemberResponse> members = onLineBidding.getMateriels().stream().filter(temp -> StatusEnum.YES.getState().equals(temp.getIsOffer())).map(temp -> {
            OnlineMemberResponse memberResponse = BeanUtil.copyProperties(temp, OnlineMemberResponse.class);
            memberResponse.setIsAward(temp.getIsPrize());
            if (StatusEnum.YES.getState().equals(temp.getIsPrize())){
                memberResponse.setPrice(temp.getPrice());
            }else {
                memberResponse.setPrice(temp.getSumPrice());
            }
            memberResponse.setMemberName(temp.getCreateMemberName());
            memberResponse.setMemberId(temp.getCreateMemberId());
            memberResponse.setMemberRoleId(temp.getCreateMemberRoleId());
            memberResponse.setPurchaseRanking(temp.getPurchaseRanking());
            memberResponse.setOnlineBiddingId(onLineBidding.getId());
            memberResponse.setReportTime(temp.getReportTime());
            return memberResponse;
        }).sorted(Comparator.comparing(OnlineMemberResponse::getReportTime)).collect(Collectors.toList());
        response.setMemers(members);
        return response;
    }


    /**
     * 查询采购竞价单内部流程记录
     */
    public List<BiddingInteriorLogResponse> getBiddingInteriorLog(Long id) {
        List<InteriorBiddingLog> interiorBiddingLogs = interiorBiddingLogRepository.findAllByBiddingId(id, Sort.by("createTime").ascending());
        if (CollectionUtils.isEmpty(interiorBiddingLogs)) {
            return new ArrayList<>();
        }
        return interiorBiddingLogs.stream().map(temp -> {
            BiddingInteriorLogResponse interiorLogResponse = new BiddingInteriorLogResponse();
            BeanUtils.copyProperties(temp, interiorLogResponse);
            interiorLogResponse.setStateName(BiddingInteriorWorkStateEnum.getName(temp.getState()));
            interiorLogResponse.setOperation(BiddingOperationStateEnum.getName(temp.getOperation()));
            interiorLogResponse.setAuditOpinion(StatusEnum.AGREE.getCHName().equals(temp.getAuditOpinion())? StatusEnum.AGREE.getName() : temp.getAuditOpinion());
            return interiorLogResponse;
        }).collect(Collectors.toList());
    }


    /**
     * 查询会员信息
     */
    public List<BiddingMemberResponse> getBiddingMembers(Long id) {
        List<BiddingDemandMember> biddingMembers = biddingDemandMemberRepository.findAllByBiddingId(id);
        if (CollectionUtils.isEmpty(biddingMembers)) {
            return new ArrayList<>();
        }
        return biddingMembers.stream().map(temp -> BeanUtil.copyProperties(temp, BiddingMemberResponse.class)).collect(Collectors.toList());
    }


    /**
     * 查询竞价单物料信息列表
     */
    public List<BiddingProductRequest> getMateriels(Long id) {
        List<BiddingProduct> biddingProducts = biddingProductRepository.findAllByBiddingId(id);
        if (CollectionUtils.isEmpty(biddingProducts)) {
            return new ArrayList<>();
        }
        return biddingProducts.stream().map(temp -> BeanUtil.copyProperties(temp, BiddingProductRequest.class)).collect(Collectors.toList());
    }

    /**
     * 查询报名信息
     */
    public List<SginUpInfoResponse> getSginUpInfo(Long biddingId) {
        OnLineBidding onLineBidding = onLineBiddingRepository.findFirstByBiddingId(biddingId);
        if (Objects.isNull(onLineBidding) || CollectionUtils.isEmpty(onLineBidding.getMateriels())) {
            return new ArrayList<>();
        }
        return onLineBidding.getMateriels().stream().filter(temp ->StatusEnum.YES.getState().equals(temp.getIsSignUp())).map(temp -> {
            SginUpInfoResponse response = new SginUpInfoResponse();
            response.setId(onLineBidding.getId());
            BeanUtils.copyProperties(temp, response);
            return response;
        }).collect(Collectors.toList());

    }

    /**
     * 查询角色名称.
     * @param roleId
     * @return
     */
    public String getRoleNameById(Long roleId){
        try {
            Wrapper<List<MemberFeignRoleVO>> roles = memberInnerControllerFeign.getRoles(Collections.singletonList(roleId));
            if(roles!=null && roles.getCode()==ResponseCode.SUCCESS.getCode()){
                List<MemberFeignRoleVO> data = roles.getData();
                if(CollectionUtil.isNotEmpty(data)){
                    return data.get(0).getRoleName();
                }
            }
        }catch (Exception e){
            log.error("请求[会员服务]获取角色名称异常：",e);
        }
        return null;
    }
}
